<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>14_异步处理-异步请求代码结构</title>
</head>
<body>

  <script>
    // 封装请求的方法: url -> promise(result)
    function requestData(url) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(url)
        }, 2000)
      })
    }

    // 方式一: 层层嵌套(回调地狱 callback hell)
    // 请求1
    // requestData('aaa').then(res => {
    //   console.log(res)
    //   // 请求2
    //   requestData(res + 'bbb').then(res => {
    //     console.log(res)
    //     // 请求3
    //     requestData(res + 'ccc').then(res => {
    //       console.log(res)
    //     })
    //   })
    // })

    // 方式二: Promise链式调用
    // requestData('aaa').then(res => {
    //   console.log(res)
    //   return requestData(res + 'bbb')
    // }).then(res => {
    //   console.log(res)
    //   return requestData(res + 'ccc')
    // }).then(res => {
    //   console.log(res)
    // })

    // 方式三: async/await
    // async function fn() {
    //   const res1 = await requestData('aaa')
    //   console.log(res1)
    // }

    // 方式四: async/await + Promise.all
    async function fn() {
      const p1 = requestData('aaa')
      const p2 = requestData('bbb')
      const p3 = requestData('ccc')

      Promise.all([p1, p2, p3]).then(res => {
        console.log(res)
      })
    }

    fn()

    // 方式五: Generator
    function* gen() {
      const res1 = yield requestData('aaa')
      console.log(res1)
      const res2 = yield requestData(res1 + 'bbb')
      console.log(res2)
      const res3 = yield requestData(res2 + 'ccc')
      console.log(res3)
    }

    // 调用
    const generator = gen()
    generator.next().value.then(res => {
      generator.next(res).value.then(res => {
        generator.next(res).value.then(res => {
          generator.next(res)
        })
      })
    })

    // 封装
    function run(generator) { 
      const g = generator()
      function next(data) {
        const result = g.next(data)
        if (result.done) return
        result.value.then(res => {
          next(res)
        })
      }
    }


  </script>
  
</body>
</html>